Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

std.child_process: enable non-standard streams #14152

Closed
wants to merge 1 commit into from

Conversation

matu3ba
Copy link
Contributor

@matu3ba matu3ba commented Jan 1, 2023

This PR simplifies the setup code and handling to minimize leaking time
for both Windows and Posix and does not touch the list approach of
Windows. Portable pipes default to pipe2 with CLOEXEC on Posix and
disabled handle inhertence on Windows except shortly before
and after the spawn.

The potential time for leaking can be long due trying to spawn on
multiple PATH and PATHEXT entries on Windows.

Leaking on Posix

  1. CLOEXEC does not take immediately effect with clone(), but after the
    setup code for the child process was run and a exec* function is executed.
    External code may at worst be long living and never do exec*.
  2. File descriptors without CLOEXEC are designed to "leak to the child",
    but every spawned process at the same time gets them as well.

File leaking on Windows can be fixed with an explicit list approach,
which might require runtime probing to not break on Kernel updates
for the parameter list.

@matu3ba matu3ba force-pushed the extra_streams branch 2 times, most recently from de0ab14 to 9bc166a Compare January 3, 2023 20:34
@matu3ba

This comment was marked as resolved.

@matu3ba matu3ba changed the title wip std.child_process: enable non-standard streams std.child_process: enable non-standard streams Jan 4, 2023
@matu3ba matu3ba marked this pull request as ready for review January 4, 2023 21:42
lib/std/child_process.zig Outdated Show resolved Hide resolved
@matu3ba matu3ba marked this pull request as draft January 4, 2023 22:32
@matu3ba

This comment was marked as resolved.

@matu3ba

This comment was marked as resolved.

@matu3ba matu3ba force-pushed the extra_streams branch 3 times, most recently from e0cd603 to b64cbee Compare January 6, 2023 19:44
@matu3ba

This comment was marked as outdated.

Copy link
Contributor Author

@matu3ba matu3ba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed todos.

lib/std/os.zig Outdated Show resolved Hide resolved
lib/std/os.zig Outdated Show resolved Hide resolved
lib/std/os.zig Outdated Show resolved Hide resolved
lib/std/os.zig Show resolved Hide resolved
test/standalone/childprocess_extrapipe/child.zig Outdated Show resolved Hide resolved
test/standalone/childprocess_extrapipe/parent.zig Outdated Show resolved Hide resolved
@matu3ba

This comment was marked as outdated.

@@ -288,6 +288,27 @@ pub fn close(fd: fd_t) void {
}
}

pub const windowsPtrDigits = 19; // log10(max(usize))
Copy link
Contributor Author

@matu3ba matu3ba Jan 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont like this solution. These are very frequent operations, so it would be nice to have the sizes next to fd_t on each platform or to have a LUT. Opinions?

@@ -1566,6 +1576,45 @@ pub fn GetEnvironmentVariableW(lpName: LPWSTR, lpBuffer: [*]u16, nSize: DWORD) G
return rc;
}

// zig fmt: off
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kept these inside for #14251, but they are generally useful for other users as well short of advanced list attributes.

@matu3ba matu3ba marked this pull request as ready for review January 10, 2023 23:42
@matu3ba
Copy link
Contributor Author

matu3ba commented Jan 10, 2023

  • fixup naming according to master

I feel like this is ready for review once CI is successful. While this is short of #14251 to prevent all leaks on Windows, I think this is very nice to use.

matu3ba added a commit to matu3ba/zig that referenced this pull request Jan 12, 2023
Panic handlers spawns itself as child process, such that child communicates passed tests encoded into a message format.
Message format: [term of process return, was_panic, message len, optional message]

This uses extra stream aka pipe to allow user logging.
Depends on ziglang#14152.
Closes ziglang#1356.
matu3ba added a commit to matu3ba/zig that referenced this pull request Jan 15, 2023
Panic handlers spawns itself as child process, such that child
communicates passed tests encoded into a message format.

Message format:
[term = process_return, was_panic, message_len, optional message]

This uses a non-standard stream=pipe to allow user logging.
Depends on ziglang#14152.
Closes ziglang#1356.
matu3ba added a commit to matu3ba/zig that referenced this pull request Jan 17, 2023
Panic test runner starts itself as child process with the test function
index representing a test block. The custom panic handler compares a
global previously written string, which is uable from within a test.
If the panic message is expected, the success count is increased and the
next test block is run. Failure ouputs the so far collected results
before the parent process terminates as well.

This means, that only one @Panic is possible within a test block and that
no follow-up code after the @Panic in the test block can be run.

Depends on ziglang#14152.
Closes ziglang#1356.
matu3ba added a commit to matu3ba/zig that referenced this pull request Jan 17, 2023
Panic test runner starts itself as child process with the test function
index representing a test block. The custom panic handler compares a
global previously written string.  If the panic message is expected, the
success count is increased and the next test block is run. On failure
the parent process prints collected results, before it terminates.

This means, that only one @Panic is possible within a test block and that
no follow-up code after the @Panic in the test block can be run.

Depends on ziglang#14152.
Closes ziglang#1356.
matu3ba added a commit to matu3ba/zig that referenced this pull request Feb 4, 2023
Panic test runner starts itself as child process with the test function
index representing a test block. The custom panic handler compares a
global previously written string.  If the panic message is expected, the
success count is increased and the next test block is run. On failure
the parent process prints collected results, before it terminates.

This means, that only one @Panic is possible within a test block and that
no follow-up code after the @Panic in the test block can be run.

Depends on ziglang#14152.
Closes ziglang#1356.
matu3ba added a commit to matu3ba/zig that referenced this pull request Feb 14, 2023
Panic test runner starts itself as child process with the test function
index representing a test block. The custom panic handler compares a
global previously written string.  If the panic message is expected, the
success count is increased and the next test block is run. On failure
the parent process prints collected results, before it terminates.

This means, that only one @Panic is possible within a test block and that
no follow-up code after the @Panic in the test block can be run.

Depends on ziglang#14152.
Closes ziglang#1356.
This PR simplifies the setup code and handling of non-standard file
descriptors and handles for Windows and Posix with main focus on pipes.

Portable pipes default to pipe2 with CLOEXEC on Posix and disabled handle
inhertance on Windows except shortly before and after the creation of
the "child process".

Leaking of file desriptors on Posix
1. CLOEXEC does not take immediately effect with clone(), but after the
setup code for the child process was run and a exec* function is executed.
External code may at worst be long living and never do exec*.
2. File descriptors without CLOEXEC are designed to "leak to the child",
but every spawned process at the same time gets them as well.

Leaking of handles on Windows
1. File leaking on Windows can be fixed with an explicit list approach
as suggested in ziglang#14251, which might require runtime probing and
allocation of the necessary process setup list. Otherwise, it might
break on Kernel updates.
2. The potential time for leaking can be long due trying to spawn on
multiple PATH and PATHEXT entries on Windows.
matu3ba added a commit to matu3ba/zig that referenced this pull request Feb 21, 2023
Panic test runner starts itself as child process with the test function
index representing a test block. The custom panic handler compares a
global previously written string.  If the panic message is expected, the
success count is increased and the next test block is run. On failure
the parent process prints collected results, before it terminates.

This means, that only one @Panic is possible within a test block and that
no follow-up code after the @Panic in the test block can be run.

Depends on ziglang#14152.
Closes ziglang#1356.
matu3ba added a commit to matu3ba/zig that referenced this pull request Apr 25, 2023
Panic test runner starts itself as child process with the test function
index representing a test block. The custom panic handler compares a
global previously written string.  If the panic message is expected, the
success count is increased and the next test block is run. On failure
the parent process prints collected results, before it terminates.

This means, that only one @Panic is possible within a test block and that
no follow-up code after the @Panic in the test block can be run.

Depends on ziglang#14152.
Closes ziglang#1356.
matu3ba added a commit to matu3ba/zig that referenced this pull request Apr 28, 2023
Panic test runner starts itself as child process with the test function
index representing a test block. The custom panic handler compares a
global previously written string.  If the panic message is expected, the
success count is increased and the next test block is run. On failure
the parent process prints collected results, before it terminates.

This means, that only one @Panic is possible within a test block and that
no follow-up code after the @Panic in the test block can be run.

Depends on ziglang#14152.
Closes ziglang#1356.
@andrewrk
Copy link
Member

It is unclear to me whether this was ever ready for review. Either way, it has succumbed to bitrot and must be refreshed in a new PR against the latest master. If you do refresh this in a new PR, please try to make it easier to review, clearly explaining the problem you are solving with a motivating use case, and don't leave open questions such as a comment on your own code that says "I dont like this solution.". Instead, do your best and then be clear that you want it to be merged.

@andrewrk andrewrk closed this Oct 19, 2023
@matu3ba
Copy link
Contributor Author

matu3ba commented Oct 19, 2023

For posterity: This contains 1. windows docs improvements for CreateProcess, 2. windows spawn process flags as I originally intended to use the advanced api, but did not use it due to external library compatibility concerns and 3. the code to unify posix and windows pipes.

Original purpose was to use it in the panic test runner, but I used instead #15991 to enable making things compatible with the server client approach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants